package org.sardine.aop;

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Method;
import java.util.List;

import org.aopalliance.aop.Advice;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class ReflectiveMethodInvocation implements MethodInvocation{
	
	protected final Object proxy;
	protected final Object target;
	protected final Method method;
	protected Object[] args;
	protected List<Advice> interceptors;
	protected int currentInterceptorIndex = -1;
	
	public ReflectiveMethodInvocation(Object proxy,Object target,Method method,Object[] args,List<Advice> interceptors){
		this.proxy = proxy;
		this.target = target;
		this.method = method;
		this.args = args;
		this.interceptors = interceptors;
	}

	public Object[] getArguments() {
		return (this.args != null ? this.args : new Object[0]);
	}

	public AccessibleObject getStaticPart() {
		return this.method;
	}

	public Object getThis() {
		return this.target;
	}

	public Method getMethod() {
		return this.method;
	}
	
	public Object proceed() throws Throwable {
		
		if(this.currentInterceptorIndex == this.interceptors.size() - 1){
			return invokeMethod();
		}
		
		Object interceptor = this.interceptors.get(++currentInterceptorIndex);
		
		return ((MethodInterceptor)interceptor).invoke(this);
	}
	
	protected Object invokeMethod() throws Throwable{
		return AopUtils.invoke(target, method, args);
	}

}
